<template>
  <div ref="refChart" class="chart"></div>
</template>
<script setup>
import { ref, defineProps, onMounted, watch, computed, onBeforeUnmount} from 'vue';
import * as eCharts from 'echarts';
import {getScale, calculateChartGrid} from './ChartUtils.js';
const refChart = ref(null);

/**组件属性 */
const props = defineProps({
  /**柱的颜色 */
  colorArray: {
    type: Object,
    default: () => {
      return {
        top: ['rgba(78,140,220,1)', 'rgba(38,109,201,1)'],
        center: ['rgba(78,140,220,1)', 'rgba(208,228,254,1)'],
        bottom: 'rgba(170,207,255,1)'
      };
    }
  },
  data: {
    type: Array,
    default: () => []
  },
  /**柱的宽度 */
  barWidth: {
    type: Number,
    default: 24
  },
  /**文字大小 */
  fontSize:{
    type: Number,
    default: 14
  }
});

/**数据监听 */
watch(() => props.data, (v) => {
  if (chart && v.length > 0) {
    const { colorArray } = props;
    let option = getOption(v, colorArray);
    option.dataZoom[0].end = v.length <= 6 ? 100 : (Math.floor(600 / v.length));
    chart.setOption(option, true);
  }
});

/**组件挂载 */
let chart;
onMounted(() => {
  const barDom = refChart.value;
  chart = eCharts.init(barDom);
  const { data, colorArray } = props;
  if (data.length > 0) {
    let option = getOption(data, colorArray);
    option.dataZoom[0].end = data.length <= 6 ? 100 : (Math.floor(600 / data.length));
    chart.setOption(option);
  }
  window.addEventListener('resize', resize);
});

/**组件取消挂载之前 */
onBeforeUnmount(()=>{
  window.removeEventListener('resize', resize);
})

/**图表大小变化重新渲染 */
const resize = () =>{
  if (chart) {
    const { data, colorArray } = props;
    let option = getOption(data, colorArray);
    option.dataZoom[0].end = data.length <= 6 ? 100 : (Math.floor(600 / data.length));
    console.log(option);
    chart.setOption(option, true);
    chart.resize();
  }
}

/**
 * 深度合并对象
 */
const deepObjectMerge = (targ, source) => {
  const target = targ;
  for (const key in source) {
    if (key.hasOwnProperty) {
      target[key] =
        target[key] && typeof target[key] === 'object'
          ? deepObjectMerge(target[key], source[key])
          : (target[key] = source[key]);
    }
  }
  return target;
};

/**
 * 组装图表series值
 */
const getOption = (data, colorArray) => {
  const xAxis = {};
  const series = getSerie(data, colorArray, '');
  xAxis.data = data.map(item => item.name);
  const option = deepObjectMerge(getDefaultOption(), {
    xAxis,
    series
  });
  return option;
};

/** */
const getDefaultOption = ()=>{
  return {
    tooltip: {
      trigger: 'axis',
      show: true,
      formatter: (params) => {
        const items = params.filter(item => item.seriesIndex % 3 === 0);
        const eleStr = createTooltipElement(items);
        return eleStr;
      },
      axisPointer: {
        type: 'shadow'
      }
    },
    dataZoom: [
      {
        type: 'inside',
        xAxisIndex: [0],
        start: 0
      }
    ],
    grid: calculateChartGrid(),
    textStyle: {
      fontSize: getScale()*props.fontSize,
      color: 'white'
    },
    yAxis: {
      type: 'value',
      axisLine: {
        show: true,
        lineStyle: {
          color: 'white'
        }
      },
      splitLine: {
        show: false
      },
      axisLabel:{
        fontSize: getScale()*props.fontSize
      }
    },
    xAxis: {
      type: '',
      axisLine: {
        show: true,
        lineStyle: {
          color: 'white'
        }
      },
      axisTick: {
        alignWithLabel: true,
        lineStyle: {
          color: 'white'
        }
      },
      axisLabel:{
        show: true,
        rotate: 25,
        fontSize: getScale()*props.fontSize
      }
    },
    series: []
  };
}

/**根据数据获取图标series值 */
const getSerie = (data, colorConfig, name) => {
  const barWidth = getScale() * props.barWidth;
  return [
    {
      name,
      type: 'pictorialBar',
      stack: name,
      barWidth,
      data,
      symbol: 'rect',
      symbolOffset: [0, -barWidth / 4],
      itemStyle: {
        color: getGradientColor(colorConfig.center)
      }
    },
    {
      name,
      type: 'pictorialBar',
      barWidth,
      data,
      symbol: 'circle',
      symbolSize: [barWidth, barWidth / 2],
      symbolPosition: 'end',
      symbolOffset: [0, -barWidth / 2],
      itemStyle: {
        color: getGradientColor(colorConfig.top)
      },
      z: 4
    },
    {
      name,
      type: 'pictorialBar',
      barWidth,
      data,
      symbol: 'circle',
      symbolSize: [barWidth, barWidth / 2],
      symbolPosition: 'start',
      z: 4,
      itemStyle: {
        color: colorConfig.bottom
      }
    }
  ];
};

/**
 * 获取渐变色配置
 * @params colors 颜色数组 包含起始颜色 结束颜色
 */
const getGradientColor = (colors) => {
  let colorStops;
  if (colors.length === 2) {
    colorStops = [
      { offset: 0, color: colors[0] },
      { offset: 1, color: colors[1] }
    ];
  } else {
    colorStops = [
      { offset: 0, color: colors[0] },
      { offset: 0.9, color: colors[1] },
      { offset: 1, color: colors[2] }
    ];
  }
  return {
    type: 'linear',
    x: 0,
    y: 0,
    x2: 0,
    y2: 1,
    colorStops
  };
};

/**创建tooltip元素，设置图标tooltip显示样式及内容 */
const createTooltipElement = (items) => {
  let eleStr = '';
  let axisName;
  items.forEach(({ color, data, seriesName, name }) => {
    axisName = name;
    let ele = '<span style="padding: 0.375rem;background: ' + color.colorStops[0].color + ';display: inline-block;border-radius: 0.375rem;"></span><span>&nbsp;&nbsp;' + seriesName + '&nbsp;&nbsp;' + data.value + '</span><br/>';
    eleStr += ele;
  });
  return '<span>' + axisName + '</span><br/>' + eleStr;
};
</script>
<style lang="less" scoped>
.chart {
  width: 100%;
  height: 100%;
}
</style>
